package com.yuxinyang.memory.admin.common;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.async.DeferredResult;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

/**
 * @author Administrator 余秀良
 * @version 1.0
 * <p>date: 2019年09月03日  10:06 </p>
 * <p>address: 四川成都 </p>
 */
@Service
public class SimpleDeferredResultHandler {
    private Map<String, Consumer<ResponseProtocol>> deferredResults;

    public SimpleDeferredResultHandler() {
        deferredResults = new ConcurrentHashMap<>();
    }

    /**
     * 将请求id与setResult映射
     *
     * @param requestId      requestId
     * @param deferredResult DeferredResult
     */
    public void process(String requestId, DeferredResult<ResponseProtocol> deferredResult) {
        // 请求超时的回调函数
        deferredResult.onTimeout(() -> {
            deferredResults.remove(requestId);
            ResponseProtocol responseProtocol = ResponseProtocol.builder().code(HttpStatus.REQUEST_TIMEOUT.value()).message("超时").build();
            deferredResult.setResult(responseProtocol);
        });

        Optional.ofNullable(deferredResults)
                .filter(t -> !t.containsKey(requestId))
                .orElseThrow(() -> new IllegalArgumentException(String.format("requestId=%s is existing", requestId)));
        // 这里的Consumer，就相当于是传入的DeferredResult对象的地址
        // 所以下面settingResult方法中"deferredResults.get(requestId)"就是Controller层创建的对象
        deferredResults.putIfAbsent(requestId, deferredResult::setResult);
    }

    /**
     * 这里相当于异步的操作方法
     * 设置DeferredResult对象的setResult方法
     *
     * @param requestId              requestId
     * @param deferredResultResponse ResponseProtocol
     */
    public void settingResult(String requestId, ResponseProtocol deferredResultResponse) {
        if (deferredResults.containsKey(requestId)) {
            Consumer<ResponseProtocol> deferredResultResponseConsumer = deferredResults.get(requestId);
            // 这里相当于DeferredResult对象的setResult方法
            deferredResultResponseConsumer.accept(deferredResultResponse);
            deferredResults.remove(requestId);
        }
    }
}
